package com.mavenq.fly.test;

import com.mavenq.fly.commons.thread.ThreadExecuteTool;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.junit.Test;
import org.springframework.util.StopWatch;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.*;
import java.util.stream.Collectors;

import static org.junit.Assert.assertTrue;

/**
 * @author 50554
 */
@Slf4j
public class CompletableFutureDemo {
    // 自定义线程池
    private static final ExecutorService executor = new ThreadPoolExecutor(8,
            16,
            60,
            TimeUnit.SECONDS,
            new LinkedBlockingDeque<>(50),
            new ThreadExecuteTool.BusThreadFactory(),
            new ThreadExecuteTool.BusRejectedExecutionHandler());

    @Test
    public void testCompletableFuture1() throws Exception {
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            int result = 100;
            System.out.println("一阶段：" + result + "--> 线程名称：" + Thread.currentThread().getName());
            return result;
        }, executor).thenApply(number -> {
            int result = number * 3;
            System.out.println("二阶段：" + result + "--> 线程名称：" + Thread.currentThread().getName());
            return result;
        });
    }

    @Test
    public void testCompletableFuture2() throws Exception {

            StringBuilder result = new StringBuilder();
            List<String> messages = Arrays.asList("a", "b", "c");
            List<CompletableFuture<String>> futures = messages.stream()
                    .map(msg -> CompletableFuture.completedFuture(msg).thenApply(s -> s.toUpperCase(Locale.ROOT)))
                    .collect(Collectors.toList());
            CompletableFuture.allOf(futures.toArray(new CompletableFuture[futures.size()])).whenComplete((v, th) -> {
                System.out.println("v:"+v +" th:"+th);
                futures.forEach(cf -> {
                    try {
                        System.out.println(cf.get());
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } catch (ExecutionException e) {
                        e.printStackTrace();
                    }
                });
                result.append("done");
            });
            assertTrue("Result was empty", result.length() > 0);


    }

    @Test
    public void testCompletableFuture3() throws Exception {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            log.info("future1 finished...");
            return "future1 result";
        }, executor);
        CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
            try {
                TimeUnit.SECONDS.sleep(6);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            log.info("future2 finished...");
            return "future2 result";
        }, executor);
//        CompletableFuture<String> future3 = CompletableFuture.supplyAsync(() -> {
//            try {
//                TimeUnit.SECONDS.sleep(3);
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            }
//            log.info("future3 finished...");
//            return "future3 result";
//        }, executor);
//        CompletableFuture<String> thenCombine = future1.thenCombine(future2, (o1, o2) -> {
//            log.info("future1.thenCombine.future2->[{}]", o1 +":联合:"+ o2);
//            return o1 +"联合"+ o2;
//        }).thenCombine(future3, (o1,o2)->{
//            log.info("future1future2.thenCombine.future3->[{}]", o1 +":联合:"+ o2);
//            return o1 +"联合"+ o2;
//        });
//        log.info("thenCombine:  "+thenCombine.get(15, TimeUnit.SECONDS));
        CompletableFuture<Void> combindFuture = CompletableFuture.allOf(future1, future2);
        try {
            combindFuture.get(5, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
//        System.out.println("future1: " + future1.isDone() + " future2: " + future2.isDone());
        System.out.println("future1:"+ future1.get());
        System.out.println("future2:"+ future2.get());

       // System.out.println("future3:"+ future3.get(3,TimeUnit.SECONDS));
        stopWatch.stop();
        log.info("总共花费时间：{} ms", stopWatch.getLastTaskTimeMillis());
    }

    @Test
    public void test() throws Exception{
        List<String> reluResults = new ArrayList<String>();
        List<String> ruleLists = Arrays.asList("a", "b", "c");
        List<CompletableFuture<String>> l =  ruleLists.stream()
                .map(e -> CompletableFuture.completedFuture(e).thenApplyAsync(s -> s, executor))
                .collect(Collectors.toList());
        CompletableFuture.allOf(l.toArray(new CompletableFuture[l.size()])).whenComplete((v, th) -> {
            l.forEach(cf -> {
                try {
                    String s = null;
                    try {
                        s = (String) cf.get(500, TimeUnit.MILLISECONDS);
                    } catch (TimeoutException e) {
                        e.printStackTrace();
                    }
                    log.info("预判推荐结果:{}", s);
                    if (StringUtils.isNotBlank(s)) {
                        reluResults.add(s);
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (ExecutionException e) {
                    e.printStackTrace();
                }
            });
        }).toCompletableFuture().join();
    }

    @Test
    public void testTime() throws ParseException {
        String time = "2022-09-09 23:59:59";
        Long l = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(time).getTime();
        System.out.println(l);
    }

    @Test
    public void setA() throws ParseException {
        LinkedList<String> l = new LinkedList<>();
        l.addLast("1");
        l.addFirst("2");
        System.out.println(l);
    }

    String a = "{\"appointDate\":\"2022-10-28\",\"channelCode\":1,\"cityCode\":\"110000\",\"cleanerId\":\"2c90844345cbe30e0145d0d094f914e8\",\"isEnableNight\":0,\"nightTimeAppoint\":false,\"serviceInfoId\":\"2c9084454b7835b0014b7841269101a9\",\"serviceItemsInfoId\":\"2c9084454b7835b0014b7841269101a9\",\"showNightTime\":false,\"supplierCode\":\"ff808081362b1c4801362e3d433c0312\",\"workHour\":2.0}";
}
